package com.spa.infrastructure.service.gaode;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.spa.infrastructure.exception.SpaException;
import com.spa.infrastructure.service.gaode.result.DistanceResult;
import com.spa.infrastructure.service.gaode.result.ReGeoResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Service
@Slf4j
public class GaodeService {

    //经纬度获取异常情况下默认的兜底距离
    private static final Long DEFAULT_DISTANCE = 3L;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${gaoDe.key}")
    private String key;

    /**
     * 计算 两点之间的距离 米
     * @param orin 出发地
     * @param destination 目的地
     */
    public Integer getDistance(String orin, String destination) {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        HttpEntity<Object> request = new HttpEntity<>(headers);
        String url = Constant.DISTANCE.replace("ORIGINS", orin)
                .replace("DESTINATION", destination)
                .replace("KEY", key);
        String data = restTemplate.getForObject(url, String.class, request);
        DistanceResult distanceResult = JSONUtil.toBean(data, DistanceResult.class);
        if (distanceResult.getStatus() == 0) {
            throw new SpaException(distanceResult.getInfo());
        }
        return distanceResult.getResults().stream().findAny().get().getDistance();
    }

    public ReGeoResult.AddressComponent regeo(String location) {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        HttpEntity<Object> request = new HttpEntity<>(headers);
        String url = Constant.REGEO.replace("LOCATION", location)
                .replace("KEY", key);
        String data = restTemplate.getForObject(url, String.class, request);
        ReGeoResult reGeoResult = JSONUtil.toBean(data, ReGeoResult.class);
        if (reGeoResult.getStatus() == 0) {
            throw new SpaException(reGeoResult.getInfo());
        }
        return reGeoResult.getRegeocode().getAddressComponent();
    }

    public String getFormattedAddress(String location) {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        HttpEntity<Object> request = new HttpEntity<>(headers);
        String url = Constant.REGEO.replace("LOCATION", location)
                .replace("KEY", key);
        String data = restTemplate.getForObject(url, String.class, request);
        ReGeoResult reGeoResult = JSONUtil.toBean(data, ReGeoResult.class);
        if (reGeoResult.getStatus() == 0) {
            throw new SpaException(reGeoResult.getInfo());
        }
        return reGeoResult.getRegeocode().getFormatted_address();
    }

    /**
     * 返回公里数
     * @param longitude1 出发地经度
     * @param latitude1 出发地纬度
     * @param longitude2 目的地经度
     * @param latitude2 目的地纬度
     * @return
     */
    public BigDecimal getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        Integer distance = getDistance(longitude1 +","+latitude1, longitude2 +","+latitude2);
        return BigDecimal.valueOf(distance).divide(BigDecimal.valueOf(1000), 2, RoundingMode.DOWN);
    }

    public BigDecimal getDistance(String sourceLon, String sourceLat, String targetLon, String targetLat) {
        double lon1 = Convert.toDouble(sourceLon, 0d);
        double lat1 = Convert.toDouble(sourceLat, 0d);
        double lon2 = Convert.toDouble(targetLon, 0d);
        double lat2 = Convert.toDouble(targetLat, 0d);
        if (lon1 == 0 || lat1 == 0 || lon2 == 0 || lat2 == 0) {
            return BigDecimal.valueOf(DEFAULT_DISTANCE);
        }
        return getDistance(lon1, lat1, lon2, lat2);
    }
}
